﻿using MesBLL.Common;
using MesDAL.DBInfo;
using MesDAL.DTO;
using MesDAL.DTO.ProcessSheet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MesBLL.EventService
{
    public class ProducePlanService : CommonService<produceplan_log>
    {
        public async Task<produceplan_log> SelectProduceplanByProcessSheet(int id)
        {
            return await Task.Run(() => GetAll().Where(x => x.process_id == id).FirstOrDefault());
        }

        public async Task<List<produceplan_log>> SelectProduceplanWithMachineAndDate(string machineNum, DateTime date)
        {
            return await Task.Run(() =>
            {
                DateTime endTime = date.AddDays(1);
                return GetAll().Where(x => x.machine_num.Equals(machineNum)).Where(x => x.estimated_start >= date && x.estimated_start < endTime).ToList();
            });
        }

        /// <summary>
        /// 检索所有未完成的计划单
        /// </summary>
        /// <returns></returns>
        public async Task<List<ProduceplanDTO>> SelectUnFinishProducePlanByDate(DateTime date)
        {
            return await Task.Run(() =>
            {
                DateTime endTime = date.AddDays(1);

                var fullEntries = serverEFModel.produceplan_log //计划表
                    .Join(
                        serverEFModel.processsheet_log,         //工艺表
                        plan => plan.process_id,
                        processsheet => processsheet.id,
                        (plan, processsheet) => new { plan, processsheet }
                    )
                    .Join(
                        serverEFModel.machine_info,             //设备表
                        combinePlan => combinePlan.plan.machine_num,
                        machine => machine.machine_num,
                        (combinePlan, machine) => new { combinePlan, machine }
                    )
                    .Join(
                        serverEFModel.workpiece_info,
                        combineWork => combineWork.combinePlan.processsheet.workpiece_id,
                        workpiece => workpiece.id,
                        (combineWork, workpiece) => new
                        {
                            combineWork,
                            workpiece
                        }
                    ).Where(x => x.combineWork.combinePlan.processsheet.isfinish == null).Where(x => x.combineWork.combinePlan.plan.estimated_start >= date && x.combineWork.combinePlan.plan.estimated_start < endTime)
                    .OrderBy(p => p.combineWork.combinePlan.plan.priority).ToList();
                List<ProduceplanDTO> list = new List<ProduceplanDTO>();
                foreach (var item in fullEntries)
                {
                    ProduceplanDTO dto = new ProduceplanDTO()
                    {
                        id = item.combineWork.combinePlan.plan.id,
                        estimated_start = item.combineWork.combinePlan.plan.estimated_start,
                        estimated_end = item.combineWork.combinePlan.plan.estimated_end,
                        priority = item.combineWork.combinePlan.plan.priority,
                        machineInfo = new MachineInfoDTO()
                        {
                            id = item.combineWork.machine.id,
                            machine_state = item.combineWork.machine.machine_state,
                            machine_supplier = item.combineWork.machine.machine_supplier,
                            machine_class = item.combineWork.machine.machine_class,
                            machine_name = item.combineWork.machine.machine_name,
                            machine_num = item.combineWork.machine.machine_num,
                        },
                        processSheet = new ProcessSheetDTO()
                        {
                            id = item.combineWork.combinePlan.processsheet.id,
                            content = item.combineWork.combinePlan.processsheet.content,
                            deadline = item.combineWork.combinePlan.processsheet.deadline,
                            estimatedhours = item.combineWork.combinePlan.processsheet.estimatedhours,
                            name = item.combineWork.combinePlan.processsheet.name,
                            number = item.combineWork.combinePlan.processsheet.number,
                            workpiece = new WorkpieceDTO()
                            {
                                id = item.workpiece.id,
                                size = item.workpiece.size,
                                date = item.workpiece.date,
                                deadline = item.workpiece.deadline,
                                material = item.workpiece.material,
                                name = item.workpiece.name,
                                number = item.workpiece.number,
                                order = item.workpiece.order,
                                qty = item.workpiece.qty,
                            },
                        }
                    };
                    if (item.combineWork.combinePlan.plan.discontinuous_date is null)
                    {
                        dto.discontinuous_date = false;
                    }
                    else
                    {
                        dto.discontinuous_date = bool.Parse(item.combineWork.combinePlan.plan.discontinuous_date);
                    }

                    list.Add(dto);
                }
                return list;
            });
        }

        /// <summary>
        /// 检索当前设备最新的计划单
        /// </summary>
        /// <param name="machine_num"></param>
        /// <returns></returns>
        public async Task<ProduceplanDTO> SelectLatestPlanWithMachine(string machine_num)
        {
            return await Task.Run(() =>
            {
                var fullEntries = serverEFModel.produceplan_log
                 .Join(
                        serverEFModel.processsheet_log,         //工艺表
                        plan => plan.process_id,
                        processsheet => processsheet.id,
                        (plan, processsheet) => new { plan, processsheet }
                    )
                    .Join(
                        serverEFModel.machine_info,             //设备表
                        combinePlan => combinePlan.plan.machine_num,
                        machine => machine.machine_num,
                        (combinePlan, machine) => new { combinePlan, machine }
                    )
                    .Join(
                        serverEFModel.workpiece_info,
                        combineWork => combineWork.combinePlan.processsheet.workpiece_id,
                        workpiece => workpiece.id,
                        (combineWork, workpiece) => new
                        {
                            combineWork,
                            workpiece
                        }
                    ).Where(x => x.combineWork.combinePlan.plan.machine_num == machine_num).OrderByDescending(p => p.combineWork.combinePlan.plan.estimated_end).FirstOrDefault();
                var item = fullEntries;
                if (item is null)
                {
                    return null;
                }
                ProduceplanDTO dto = new ProduceplanDTO()
                {
                    id = item.combineWork.combinePlan.plan.id,
                    estimated_start = item.combineWork.combinePlan.plan.estimated_start,
                    estimated_end = item.combineWork.combinePlan.plan.estimated_end,
                    priority = item.combineWork.combinePlan.plan.priority,
                    machineInfo = new MachineInfoDTO()
                    {
                        id = item.combineWork.machine.id,
                        machine_state = item.combineWork.machine.machine_state,
                        machine_supplier = item.combineWork.machine.machine_supplier,
                        machine_class = item.combineWork.machine.machine_class,
                        machine_name = item.combineWork.machine.machine_name,
                        machine_num = item.combineWork.machine.machine_num,
                    },
                    processSheet = new ProcessSheetDTO()
                    {
                        id = item.combineWork.combinePlan.processsheet.id,
                        content = item.combineWork.combinePlan.processsheet.content,
                        deadline = item.combineWork.combinePlan.processsheet.deadline,
                        estimatedhours = item.combineWork.combinePlan.processsheet.estimatedhours,
                        name = item.combineWork.combinePlan.processsheet.name,
                        number = item.combineWork.combinePlan.processsheet.number,
                        workpiece = new WorkpieceDTO()
                        {
                            id = item.workpiece.id,
                            size = item.workpiece.size,
                            date = item.workpiece.date,
                            deadline = item.workpiece.deadline,
                            material = item.workpiece.material,
                            name = item.workpiece.name,
                            number = item.workpiece.number,
                            order = item.workpiece.order,
                            qty = item.workpiece.qty,
                        },
                    }
                };
                if (item.combineWork.combinePlan.plan.discontinuous_date is null)
                {
                    dto.discontinuous_date = false;
                }
                else
                {
                    dto.discontinuous_date = bool.Parse(item.combineWork.combinePlan.plan.discontinuous_date);
                }
                return dto;
            });
        }

        public async Task<List<ProduceplanDTO>> SelectUnFinishProducePlanByMachineId(int id)
        {
            return await Task.Run(() =>
            {
                var fullEntries = serverEFModel.produceplan_log //计划表
                    .Join(
                        serverEFModel.processsheet_log,         //工艺表
                        plan => plan.process_id,
                        processsheet => processsheet.id,
                        (plan, processsheet) => new { plan, processsheet }
                    )
                    .Join(
                        serverEFModel.machine_info,             //设备表
                        combinePlan => combinePlan.plan.machine_num,
                        machine => machine.machine_num,
                        (combinePlan, machine) => new { combinePlan, machine }
                    )
                    .Join(
                        serverEFModel.workpiece_info,
                        combineWork => combineWork.combinePlan.processsheet.workpiece_id,
                        workpiece => workpiece.id,
                        (combineWork, workpiece) => new
                        {
                            combineWork,
                            workpiece
                        }
                    ).Where(x => x.combineWork.combinePlan.processsheet.isfinish == null).Where(x => x.combineWork.machine.id == id)
                    .OrderBy(p => p.combineWork.combinePlan.plan.priority).ToList();
                List<ProduceplanDTO> list = new List<ProduceplanDTO>();
                foreach (var item in fullEntries)
                {
                    ProduceplanDTO dto = new ProduceplanDTO()
                    {
                        id = item.combineWork.combinePlan.plan.id,
                        estimated_start = item.combineWork.combinePlan.plan.estimated_start,
                        estimated_end = item.combineWork.combinePlan.plan.estimated_end,
                        priority = item.combineWork.combinePlan.plan.priority,
                        machineInfo = new MachineInfoDTO()
                        {
                            id = item.combineWork.machine.id,
                            machine_state = item.combineWork.machine.machine_state,
                            machine_supplier = item.combineWork.machine.machine_supplier,
                            machine_class = item.combineWork.machine.machine_class,
                            machine_name = item.combineWork.machine.machine_name,
                            machine_num = item.combineWork.machine.machine_num,
                        },
                        processSheet = new ProcessSheetDTO()
                        {
                            id = item.combineWork.combinePlan.processsheet.id,
                            content = item.combineWork.combinePlan.processsheet.content,
                            deadline = item.combineWork.combinePlan.processsheet.deadline,
                            estimatedhours = item.combineWork.combinePlan.processsheet.estimatedhours,
                            name = item.combineWork.combinePlan.processsheet.name,
                            number = item.combineWork.combinePlan.processsheet.number,
                            workpiece = new WorkpieceDTO()
                            {
                                id = item.workpiece.id,
                                size = item.workpiece.size,
                                date = item.workpiece.date,
                                deadline = item.workpiece.deadline,
                                material = item.workpiece.material,
                                name = item.workpiece.name,
                                number = item.workpiece.number,
                                order = item.workpiece.order,
                                qty = item.workpiece.qty,
                            },
                        }
                    };
                    list.Add(dto);
                }
                return list;
            });
        }

        /// <summary>
        /// 通过id检索计划单
        /// </summary>
        /// <param name="planId"></param>
        /// <returns></returns>
        public async Task<ProduceplanDTO> SelectProducePlanById(int planId)
        {
            return await Task.Run(() =>
            {
                var fullEntries = serverEFModel.produceplan_log //计划表
                    .Join(
                        serverEFModel.processsheet_log,         //工艺表
                        plan => plan.process_id,
                        processsheet => processsheet.id,
                        (plan, processsheet) => new { plan, processsheet }
                    )
                    .Join(
                        serverEFModel.machine_info,             //设备表
                        combinePlan => combinePlan.plan.machine_num,
                        machine => machine.machine_num,
                        (combinePlan, machine) => new { combinePlan, machine }
                    )
                    .Join(
                        serverEFModel.workpiece_info,
                        combineWork => combineWork.combinePlan.processsheet.workpiece_id,
                        workpiece => workpiece.id,
                        (combineWork, workpiece) => new
                        {
                            combineWork,
                            workpiece
                        }
                    ).Where(x => x.combineWork.combinePlan.plan.id == planId).FirstOrDefault();
                var item = fullEntries;
                ProduceplanDTO dto = new ProduceplanDTO()
                {
                    id = item.combineWork.combinePlan.plan.id,
                    estimated_start = item.combineWork.combinePlan.plan.estimated_start,
                    estimated_end = item.combineWork.combinePlan.plan.estimated_end,
                    priority = item.combineWork.combinePlan.plan.priority,
                    machineInfo = new MachineInfoDTO()
                    {
                        id = item.combineWork.machine.id,
                        machine_state = item.combineWork.machine.machine_state,
                        machine_supplier = item.combineWork.machine.machine_supplier,
                        machine_class = item.combineWork.machine.machine_class,
                        machine_name = item.combineWork.machine.machine_name,
                        machine_num = item.combineWork.machine.machine_num,
                    },
                    processSheet = new ProcessSheetDTO()
                    {
                        id = item.combineWork.combinePlan.processsheet.id,
                        content = item.combineWork.combinePlan.processsheet.content,
                        deadline = item.combineWork.combinePlan.processsheet.deadline,
                        estimatedhours = item.combineWork.combinePlan.processsheet.estimatedhours,
                        name = item.combineWork.combinePlan.processsheet.name,
                        number = item.combineWork.combinePlan.processsheet.number,
                        workpiece = new WorkpieceDTO()
                        {
                            id = item.workpiece.id,
                            size = item.workpiece.size,
                            date = item.workpiece.date,
                            deadline = item.workpiece.deadline,
                            material = item.workpiece.material,
                            name = item.workpiece.name,
                            number = item.workpiece.number,
                            order = item.workpiece.order,
                            qty = item.workpiece.qty,
                        },
                    }
                };
                return dto;
            });
        }

        /// <summary>
        /// 检索当前日期之后所有未完成的计划单
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        public async Task<List<ProduceplanDTO>> SelectUnFinishProducePlanAfterDate(DateTime date)
        {
            return await Task.Run(() =>
            {
                DateTime tomorrow = date.AddDays(1);
                var listquary = GetAll().Where(x => x.estimated_start >= date.Date)
                .GroupJoin(serverEFModel.processsheet_log, producePlan => producePlan.process_id, process => process.id, (producePlan, process) => new { producePlan, process })
                .SelectMany(o => o.process.DefaultIfEmpty(), (o, process) => new { o.producePlan, process }).ToList();
                List<ProduceplanDTO> list = new List<ProduceplanDTO>();
                foreach (var o in listquary)
                {
                    ProduceplanDTO dto = new ProduceplanDTO
                    {
                        id = o.producePlan.id,
                        estimated_start = o.producePlan.estimated_start,
                        processSheet = new ProcessSheetDTO()
                        {
                            id = o.process.id,
                            content = o.process.content,
                            deadline = o.process.deadline,
                            estimatedhours = o.process.estimatedhours,
                            name = o.process.name,
                            number = o.process.number,
                            workpiece = new WorkpieceDTO() { id = o.process.id }
                        },
                        estimated_end = o.producePlan.estimated_end,
                        machineInfo = new MachineInfoDTO() { machine_num = o.producePlan.machine_num },
                        priority = o.producePlan.priority
                    };
                    if (!(o.process.isfinish is null))
                    {
                        continue;
                    }
                    list.Add(dto);
                }
                return list;
            });
        }

        /// <summary>
        /// 检索设备中未完成的计划单
        /// </summary>
        /// <param name="machineNum"></param>
        /// <returns></returns>
        public async Task<List<ProduceplanDTO>> SelectUnFinishProducePlanByMachineNum(string machineNum)
        {
            return await Task.Run(() =>
            {
                var planQury = GetAll().Where(x => x.machine_num.Equals(machineNum)).Where(x => x.priority > 0)
                .GroupJoin(serverEFModel.processsheet_log, plan => plan.process_id, process => process.id, (plan, process) => new { plan, process })
                .SelectMany(o => o.process.DefaultIfEmpty(), (o, process) => new { producePlan = o.plan, process })
                .GroupJoin(serverEFModel.workpiece_info, plan => plan.process.workpiece_id, workpiece => workpiece.id, (plan, workpiece) => new { plan, workpiece })
                .SelectMany(o => o.workpiece.DefaultIfEmpty(), (o, workpiece) => new { o.plan.process, o.plan.producePlan, workpiece }).ToList();
                List<ProduceplanDTO> list = new List<ProduceplanDTO>();
                foreach (var o in planQury)
                {
                    ProduceplanDTO dto = new ProduceplanDTO
                    {
                        id = o.producePlan.id,
                        estimated_start = o.producePlan.estimated_start,
                        processSheet = new ProcessSheetDTO()
                        {
                            id = o.process.id,
                            content = o.process.content,
                            deadline = o.process.deadline,
                            estimatedhours = o.process.estimatedhours,
                            name = o.process.name,
                            number = o.process.number,
                            workpiece = new WorkpieceDTO()
                            {
                                id = o.workpiece.id,
                                size = o.workpiece.size,
                                date = o.workpiece.date,
                                deadline = o.workpiece.deadline,
                                material = o.workpiece.material,
                                name = o.workpiece.name,
                                number = o.workpiece.number,
                                order = o.workpiece.order,
                                qty = o.workpiece.qty,
                            }
                        },
                        estimated_end = o.producePlan.estimated_end,
                        machineInfo = new MachineInfoDTO() { machine_num = o.producePlan.machine_num },
                        priority = o.producePlan.priority,
                    };
                    if (o.producePlan.discontinuous_date is null)
                    {
                        dto.discontinuous_date = false;
                    }
                    else
                    {
                        dto.discontinuous_date = bool.Parse(o.producePlan.discontinuous_date);
                    }
                    if (!(o.process.isfinish is null))
                    {
                        continue;
                    }
                    list.Add(dto);
                }
                list = list.OrderBy(x => x.priority).ToList();
                return list;
            });
        }

        /// <summary>
        /// 整体修改编辑计划单
        /// </summary>
        /// <param name="needEditList"></param>
        /// <returns></returns>
        public async Task<bool> EditProducePlanList(List<ProduceplanDTO> needEditList)
        {
            return await Task.Run(() =>
            {
                List<int> idList = new List<int>();
                foreach (var item in needEditList)
                {
                    idList.Add(item.id);
                }
                var quary = serverEFModel.produceplan_log.Where(x => idList.Contains(x.id)).ToList();
                foreach (var item in quary)
                {
                    ProduceplanDTO dto = needEditList.Find(x => x.id == item.id);
                    item.machine_num = dto.machineInfo.machine_num;
                    item.priority = dto.priority;
                    item.estimated_start = dto.estimated_start;
                    item.estimated_end = dto.estimated_end;
                    item.process_id = dto.processSheet.id;
                }
                serverEFModel.SaveChanges();
                return true;
            });
        }

        /// <summary>
        /// 查询所有尚未完成的计划单
        /// </summary>
        /// <returns></returns>
        public async Task<List<ProduceplanDTO>> SelectAllUnFinishProducePlan()
        {
            return await Task.Run(() =>
            {
                var planQury = GetAll().Where(x => x.priority > 0)
                 .GroupJoin(serverEFModel.processsheet_log, plan => plan.process_id, process => process.id, (plan, process) => new { plan, process })
                 .SelectMany(o => o.process.DefaultIfEmpty(), (o, process) => new { producePlan = o.plan, process })
                 .GroupJoin(serverEFModel.workpiece_info, plan => plan.process.workpiece_id, workpiece => workpiece.id, (plan, workpiece) => new { plan, workpiece })
                 .SelectMany(o => o.workpiece.DefaultIfEmpty(), (o, workpiece) => new { o.plan.process, o.plan.producePlan, workpiece }).ToList();
                List<ProduceplanDTO> list = new List<ProduceplanDTO>();
                foreach (var o in planQury)
                {
                    ProduceplanDTO dto = new ProduceplanDTO
                    {
                        id = o.producePlan.id,
                        estimated_start = o.producePlan.estimated_start,
                        processSheet = new ProcessSheetDTO()
                        {
                            id = o.process.id,
                            content = o.process.content,
                            deadline = o.process.deadline,
                            estimatedhours = o.process.estimatedhours,
                            name = o.process.name,
                            number = o.process.number,
                            workpiece = new WorkpieceDTO()
                            {
                                id = o.workpiece.id,
                                size = o.workpiece.size,
                                date = o.workpiece.date,
                                deadline = o.workpiece.deadline,
                                material = o.workpiece.material,
                                name = o.workpiece.name,
                                number = o.workpiece.number,
                                order = o.workpiece.order,
                                qty = o.workpiece.qty,
                            }
                        },
                        estimated_end = o.producePlan.estimated_end,
                        machineInfo = new MachineInfoDTO() { machine_num = o.producePlan.machine_num },
                        priority = o.producePlan.priority
                    };
                    if (!(o.process.isfinish is null))
                    {
                        continue;
                    }
                    list.Add(dto);
                }
                list = list.OrderBy(x => x.priority).ToList();
                return list;
            });
        }
    }
}
